package com.lmf.juc.Lock.case1;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 多线程编程步骤：
 *      1.定义资源类
 *      2.创建多个线程同时去调用资源类
 *
 *  以下是创建一个多线程抢票案例：卖票窗口，利用Lock接口的可重入锁实现
 */
//定义资源类
public class SaleTicket {

    //声明总票数
    private int number = 30;

    /**
     * 创建可重入锁：
     * ReentrantLock(Boolean fair):
     *      1.若 fair = false：则表示使用非公平锁，这样效率较高，但会导致有的线程直接饿死。（即，没有访问资源类的机会，全靠速度抢）
     *      2.若 fair = true：则表示使用公平锁，这样效率较低，但是会保证每个线程，都能访问到这个资源类。（线程会自动排队）
     */
    private final Lock lock = new ReentrantLock(true);

    //创建买票的方法:使用同步锁
    public void saleTickets() throws InterruptedException {
        //手动上锁
        lock.lock();

        try {
            //判断一下还有没有票
            if (number > 0) {
                number--;
                System.out.println(Thread.currentThread().getName() + ":买了1张票，还剩：" + number);
            }else {
                //没有票就结束该方法
                System.out.println("票已经卖完了！！！");

                //线程睡眠
//            Thread.sleep(Long.MAX_VALUE);

                //线程结束
//                Thread.currentThread().stop();
            }
        }finally {
            //手动解锁,为了保证出现异常也可以解锁，一般放在finally里面
            lock.unlock();
        }

    }
}
